package com.info.zhiduoduo.core.service.impl;

import com.info.zhiduoduo.alipay.constant.AlipayPrincipalEnum;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceUserType;
import com.info.zhiduoduo.common.constants.invoice.InvoiceType;
import com.info.zhiduoduo.common.constants.project.ProjectType;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.RandomUtil;
import com.info.zhiduoduo.core.service.CoreInvoiceService;
import com.info.zhiduoduo.repository.dto.company.CompanyDetailDto;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceInfoDto;
import com.info.zhiduoduo.repository.dto.maker.MakerDetailDto;
import com.info.zhiduoduo.repository.entity.company.Company;
import com.info.zhiduoduo.repository.entity.crowdsource.ContractorInvoice;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceInvoice;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceProject;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceProjectItem;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProject;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProjectItem;
import com.info.zhiduoduo.repository.entity.invoice.Invoice;
import com.info.zhiduoduo.repository.mapper.company.CompanyMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyProjectMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceAccountMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceProjectMapper;
import com.info.zhiduoduo.repository.mapper.entrustmentproject.EntrustmentProjectItemMapper;
import com.info.zhiduoduo.repository.mapper.maker.MakerMapper;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class CoreInvoiceServiceImpl implements CoreInvoiceService {

	@Resource
	MakerMapper makerMapper;
	@Resource
	CompanyMapper companyMapper;
	@Resource
	CompanyProjectMapper companyProjectMapper;
	@Resource
	CrowdsourceProjectMapper crowdsourceProjectMapper;
	@Resource
	EntrustmentProjectItemMapper entrustmentProjectItemMapper;
	@Resource
	CrowdsourceAccountMapper crowdsourceAccountMapper;

	@Override
	public Invoice createZhiduoduoProjectInvoice(int projectid) {
		Invoice invoice = companyProjectMapper.getPendingInvoiceDetail(projectid);
		if (invoice == null) return null;

		Date projectfinishtime = invoice.getProjectfinishtime();
		String applyno = RandomUtil.createRandomNo("INVO_", "");
		invoice.setApplyno(applyno)
				.setProjectType(ProjectType.ZHIDUODUO)
				.setState(Constants.invoicestate_1)
				.setCreatetime(projectfinishtime)
				.setStarttime(projectfinishtime);

		invoice.insert();
		return invoice;
	}

	@Override
	public Invoice createCrowdsourceProjectInvoice(int projectid) {
		Invoice invoice = crowdsourceProjectMapper.getPendingInvoiceDetail(projectid);
		String applyno = RandomUtil.createRandomNo("CSIN_", "");
		invoice.setApplyno(applyno)
				.setProjectType(ProjectType.CROWDSOURCE)
				.setState(Constants.invoicestate_2)
				.setProjectfinishtime(new Date());
		if (invoice.insert()) return invoice;
		return null;
	}

	@Override
	public void createEntrustZhiduoduoProjectInvoice(List<EntrustmentProjectItem> itemList) {
		if (CollectionUtils.isEmpty(itemList)) return;

		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(itemList.get(0).getImportId());

		// 每个创客 分别创建发票
		itemList.stream().collect(Collectors.groupingBy(EntrustmentProjectItem::getEntrusteeId)).forEach((entrusteeid, list) -> {
			EntrustmentProjectItem projectItem = itemList.get(0);
			BigDecimal importedTaxInclusiveAmount = list.stream()
					.map(EntrustmentProjectItem::getInvoiceAmount)
					.reduce(BigDecimal::add)
					.orElse(BigDecimal.ZERO);
			Integer compid = projectItem.getCompid();
			Company company = companyMapper.selectById(compid);
			MakerDetailDto maker = makerMapper.getUserDetail(entrusteeid);

			String applyno = RandomUtil.createRandomNo("INVO_", "");
			Invoice invoice = new Invoice().setApplyno(applyno)
					.setProjectid(projectItem.getImportId()) // 记录发单的id. 整个导入发单项目开一张发票给发单企业
					.setPartyId(entrustmentProject.getPartyId())
					.setPayId(entrustmentProject.getPayId())
					.setProjectname(projectItem.getName()) // 取第一个子项目的项目名
					.setProjectType(projectItem.getProjectType())
					.setInvoicetype(projectItem.getInvoiceType())
					.setInvoiceAmount(importedTaxInclusiveAmount)
					.setContent(projectItem.getInvoiceContent())
					.setUserid(maker.getUserid()) // 受托人创客id
					.setUsername(maker.getUsername())
					.setActualName(maker.getRealname())
					.setUserTaxno(maker.getCreditcode())
					.setUserAcctbank(maker.getAcctno())
					.setUserAcctno(maker.getAcctno())
					.setUserTelephone(maker.getPhone())
					.setUserAddress(maker.getAddr())
					.setCompid(compid)
					.setCompname(company.getCompname())
					.setCompTaxno(company.getCreditcode())
					.setCompAcctbank(company.getAcctbank())
					.setCompAcctno(company.getAcctno())
					.setCompTelephone(company.getTelephone())
					.setCompAddress(company.getCompaddress())
					.setContactname(company.getContactname())
					.setContactphone(company.getContactphone())
					.setState(Constants.invoicestate_1)
					.setProjectfinishtime(new Date())
					.setCreatetime(new Date())
					.setStarttime(new Date());

			invoice.insert();
		});
	}

	@Override
	public void createEntrustCrowdsourceProjectInvoice(List<EntrustmentProjectItem> itemList) {
		if (CollectionUtils.isEmpty(itemList)) return;

		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(itemList.get(0).getImportId());
		Integer actualCompanyId = entrustmentProject.getActualCompanyId();

		// 每个委托主体 分别创建发票
		itemList.stream().collect(Collectors.groupingBy(EntrustmentProjectItem::getPrincipalId)).forEach((principalId, list) -> {
			EntrustmentProjectItem projectItem = itemList.get(0);
			BigDecimal importedTaxInclusiveAmount = list.stream()
					.map(EntrustmentProjectItem::getInvoiceAmount)
					.reduce(BigDecimal::add)
					.orElse(BigDecimal.ZERO);
			Integer compid = projectItem.getCompid();
			Company company = companyMapper.selectById(compid);

			String applyno = RandomUtil.createRandomNo("INVO_", "");
			Invoice invoice = new Invoice().setApplyno(applyno)
					.setProjectid(projectItem.getImportId()) // 记录发单的id. 整个导入发单项目开一张发票给发单企业
				    .setPartyId(entrustmentProject.getPartyId())
				    .setPayId(entrustmentProject.getPayId())
					.setProjectname(projectItem.getName()) // 取第一个子项目的项目名
					.setProjectType(projectItem.getProjectType())
					.setInvoicetype(company.getInvoiceType())
					.setInvoiceAmount(importedTaxInclusiveAmount)
					.setContent(projectItem.getInvoiceContent())
					.setUserid(principalId) // 委托主体id
					.setUsername(AlipayPrincipalEnum.findById(principalId).name)
					.setCompid(compid)
					.setCompname(company.getCompname())
					.setCompTaxno(company.getCreditcode())
					.setCompAcctbank(company.getAcctbank())
					.setCompAcctno(company.getAcctno())
					.setCompTelephone(company.getTelephone())
					.setCompAddress(company.getCompaddress())
					.setContactname(company.getContactname())
					.setContactphone(company.getContactphone())
					.setState(Constants.invoicestate_2)
					.setProjectfinishtime(new Date())
					.setCreatetime(new Date())
					.setActualCompanyId(actualCompanyId)
					.setStarttime(new Date());

			invoice.insert();
		});
	}

	@Override
	public void createEntrustCrowdsourceProjectMakerInvoice(List<EntrustmentProjectItem> itemList) {
		if (CollectionUtils.isEmpty(itemList)) return;
		EntrustmentProject entrustmentProject = new EntrustmentProject().selectById(itemList.get(0).getImportId());

		// 每个创客 分别创建发票
		itemList.stream().collect(Collectors.groupingBy(EntrustmentProjectItem::getEntrusteeId)).forEach((entrusteeid, list) -> {
			EntrustmentProjectItem projectItem = itemList.get(0);
			BigDecimal amount = list.stream().map(EntrustmentProjectItem::getAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
			Integer compid = projectItem.getCompid();
			MakerDetailDto userDetail = makerMapper.getUserDetail(projectItem.getEntrusteeId());
			String realName = userDetail != null ? userDetail.getRealname() : "";
			Company company = companyMapper.selectById(compid);

			CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().setProjectid(projectItem.getImportId())
					.setPartyId(entrustmentProject.getPartyId())
					.setPayId(entrustmentProject.getPayId())
					.setProjectType(projectItem.getProjectType())
					.setProjectName(projectItem.getName())
					.setCrowdsourceid(projectItem.getEntrusteeId()) // 受托人创客id
					.setUserType(CrowdsourceUserType.STUDIO)
					.setRealName(realName)
					.setInvoiceType(String.valueOf(projectItem.getInvoiceType()))
					.setInvoiceContent(projectItem.getInvoiceContent())
					// 生成的创客成本票金额：【税后所得】
					.setProjectAmount(amount)
					.setCompid(compid)
					.setCompname(company.getCompname())
					.setState(Constants.invoicestate_1);
			crowdsourceInvoice.insert();
		});
	}

	@Override
	public CrowdsourceInvoice createCrowdsourceProjectMakerInvoice(int projectItemId) {
		CrowdsourceProjectItem item = new CrowdsourceProjectItem().selectById(projectItemId);
		CrowdsourceProject project = new CrowdsourceProject().selectById(item.getProjectid());
		String realName = getUserRealName(item.getUserid(), item.getUserType());
		CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().setProjectid(item.getProjectid())
				.setProjectType(ProjectType.CROWDSOURCE)
				.setProjectItemId(projectItemId)
				.setProjectName(project.getProjectName())
				.setCrowdsourceid(item.getUserid())
				.setUserType(item.getUserType())
				.setRealName(realName)
				.setInvoiceType(String.valueOf(InvoiceType.GENERAL))
				.setInvoiceContent(project.getInvoiceContent())
				.setProjectAmount(item.getProjectAmount())
				.setCompid(project.getCompid())
				.setCompname(project.getCompname())
				.setPartyId(project.getPartyId())
				.setPayId(project.getPayId())
				.setState(Constants.invoicestate_1);
		crowdsourceInvoice.insert();
		return crowdsourceInvoice;
	}

	@Override
	public ContractorInvoice createContractorInvoice(int projectId) {
		CrowdsourceProject project = new CrowdsourceProject().selectById(projectId);

		BigDecimal applyAmount = project.getProjectTotalAmount()
				.add(project.getProjectTotalAmount()
						.multiply(project.getTaxSourceCostRate()));
		ContractorInvoice contractorInvoice = new ContractorInvoice().setProjectid(projectId)
				.setProjectName(project.getProjectName())
				.setInvoiceType(String.valueOf(InvoiceType.SPECIAL))
				.setInvoiceContent(project.getInvoiceContent())
				.setProjectAmount(project.getProjectTotalAmount())
				.setCompid(project.getCompid())
				.setCompname(project.getCompname())
				.setPartyId(project.getPartyId())
				.setState(Constants.CROWDSOURCE_INVOICE_STATE_1)
				.setApplyAmount(applyAmount);
		contractorInvoice.insert();
		return contractorInvoice;
	}

	/**
	 * 获取用户真实名称
	 * @param userid
	 * @param userType
	 * @return
	 */
	public String getUserRealName(Integer userid, Integer userType) {
		String realName = "";
		if (NumberUtil.equals(userType, CrowdsourceUserType.NATURAL_PERSON)) {
			CrowdsourceInfoDto info = crowdsourceAccountMapper.getInfo(userid);
			realName = info != null ? info.getRealname() : "";
		} else if (NumberUtil.equals(userType, CrowdsourceUserType.STUDIO)) {
			MakerDetailDto userDetail = makerMapper.getUserDetail(userid);
			realName = userDetail != null ? userDetail.getRealname() : "";
		}
		return realName;
	}
}
